package Test;

import static org.junit.Assert.*;
import leducHoldem.Data.Board;
import leducHoldem.Data.Move;
import leducHoldem.Data.SimulationBoard;

import org.junit.Test;

public class SimulationBoardTest {

	@Test
	public void makeMoveTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("J"));
		
		board.makeMoveForCard(new Move("ch"), new Move("Q"));

		assertEquals("Q.ch", board.id);
		assertEquals(2, board.currentPlayer);
		assertEquals(new Move("ch"), board.history.peek());
		assertEquals(2, board.getPot());
		assertEquals(2, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("ch")));
		assertEquals(true, board.getAvailableActions().contains(new Move("b")));
	}
	
	@Test
	public void reverseMoveTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("ch"), new Move("Q"));
		board.reverseMove(new Move("J"));

		assertEquals("J", board.id);
		assertEquals(1, board.currentPlayer);
		assertEquals(0, board.history.size());
		assertEquals(2, board.getPot());
		assertEquals(2, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("ch")));
		assertEquals(true, board.getAvailableActions().contains(new Move("b")));
	}
	
	@Test
	public void makeMoveWithBetTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		
		assertEquals("Q.b", board.id);
		assertEquals(2, board.currentPlayer);
		assertEquals(1, board.history.size());
		assertEquals(4, board.getPot());
		assertEquals(3, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("c")));
		assertEquals(true, board.getAvailableActions().contains(new Move("r")));
		assertEquals(true, board.getAvailableActions().contains(new Move("f")));
	}
	
	@Test
	public void makeMoveAroundFlopTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		
		assertEquals("Q.b.c.J", board.id);
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(new Move("J"), board.table);
		assertEquals(1, board.currentPlayer);
		assertEquals(3, board.history.size());
		assertEquals(6, board.getPot());
		assertEquals(2, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("b")));
		assertEquals(true, board.getAvailableActions().contains(new Move("ch")));
	}
	
	@Test
	public void makeMoveAndReverseMoveAroundFlopTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		board.reverseMove(new Move("K"));
		
		assertEquals("K.b.c", board.id);
		assertEquals(new Move("K"), board.getCurrentCard());
		assertNull(board.table);
		assertEquals(1, board.currentPlayer);
		assertEquals(2, board.history.size());
		assertEquals(6, board.getPot());
	}
	
	@Test
	public void reverseMoveWithBetTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.reverseMove(new Move("J"));

		assertEquals("J", board.id);
		assertEquals(1, board.currentPlayer);
		assertEquals(0, board.history.size());
		assertEquals(2, board.getPot());
		assertEquals(2, board.getAvailableActions().size());
		assertEquals(new Move("J"), board.getCurrentCard());
		assertEquals(true, board.getAvailableActions().contains(new Move("ch")));
		assertEquals(true, board.getAvailableActions().contains(new Move("b")));
	}
	
	@Test
	public void evaluateTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));

		assertEquals("Q.b", board.id);
		assertEquals(2, board.currentPlayer);
		assertEquals(1, board.history.size());
		assertEquals(4, board.getPot());
		assertEquals(3, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("c")));
		assertEquals(true, board.getAvailableActions().contains(new Move("r")));
		assertEquals(true, board.getAvailableActions().contains(new Move("f")));
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(-4, board.evaluate((byte)2)[0], 0.001);
		assertEquals(0, board.evaluate((byte)2)[1], 0.001);
		assertEquals(4, board.evaluate((byte)2)[2], 0.001);
		
	}
	
	@Test
	public void evaluateTestAfterFlop() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		board.makeMoveForCard(new Move("b"), new Move("Q"));

		assertEquals("Q.b.c.J.b", board.id);
		assertEquals(2, board.currentPlayer);
		assertEquals(4, board.history.size());
		assertEquals(10, board.getPot());
		assertEquals(3, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("c")));
		assertEquals(true, board.getAvailableActions().contains(new Move("r")));
		assertEquals(true, board.getAvailableActions().contains(new Move("f")));
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(10, board.evaluate((byte)2)[0], 0.001);
		assertEquals(0, board.evaluate((byte)2)[1], 0.001);
		assertEquals(10, board.evaluate((byte)2)[2], 0.001);
		
	}
	
	@Test
	public void evaluateTestAfterFlopOnTerminalBoard() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("K"), new Move("Q"));
		board.makeMoveForCard(new Move("ch"), new Move("Q"));
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));

		assertEquals("Q.b.c.K.ch.b.c", board.id);
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(-14, board.evaluate((byte)2)[0], 0.001);
		assertEquals(0, board.evaluate((byte)2)[1], 0.001);
		assertEquals(14, board.evaluate((byte)2)[2], 0.001);
		
	}
	
	@Test
	public void evaluateTestAfterFlopOnTerminalBoardWithSecondPlayer() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("K"), new Move("Q"));
		board.makeMoveForCard(new Move("ch"), new Move("Q"));
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));

		assertEquals("Q.b.c.K.ch.b.c", board.id);
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(14, board.evaluate((byte)1)[0], 0.001);
		assertEquals(0, board.evaluate((byte)1)[1], 0.001);
		assertEquals(-14, board.evaluate((byte)1)[2], 0.001);
		
	}
	
	@Test
	public void evaluateTestWithSecondPlayer() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		board.makeMoveForCard(new Move("b"), new Move("Q"));

		assertEquals("Q.b.c.J.b", board.id);
		assertEquals(2, board.currentPlayer);
		assertEquals(4, board.history.size());
		assertEquals(10, board.getPot());
		assertEquals(3, board.getAvailableActions().size());
		assertEquals(true, board.getAvailableActions().contains(new Move("c")));
		assertEquals(true, board.getAvailableActions().contains(new Move("r")));
		assertEquals(true, board.getAvailableActions().contains(new Move("f")));
		assertEquals(new Move("Q"), board.getCurrentCard());
		assertEquals(-10, board.evaluate((byte)1)[0], 0.001);
		assertEquals(0, board.evaluate((byte)1)[1], 0.001);
		assertEquals(-10, board.evaluate((byte)1)[2], 0.001);
		
	}
	
	@Test
	public void anotherEvaluateTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("c"), new Move("J"));
		board.makeMoveForCard(new Move("K"), new Move("J"));
		board.makeMoveForCard(new Move("ch"), new Move("J"));
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("r"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		

		assertEquals(-22, board.evaluate((byte)1)[0], 0.001);
		assertEquals(0, board.evaluate((byte)1)[1], 0.001);
		assertEquals(22, board.evaluate((byte)1)[2], 0.001);
		
	}
	
	@Test
	public void isBeforeChanceMoveTest() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));

		assertEquals(true, board.isBeforeChanceMove(new Move("c")));
		assertEquals(false, board.isBeforeChanceMove(new Move("r")));
		
	}
	
	@Test
	public void isBeforeChanceMoveTestWithFirstMoveTested() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));

		assertEquals(false, board.isBeforeChanceMove(new Move("ch")));
		assertEquals(false, board.isBeforeChanceMove(new Move("b")));
		
	}
	
	@Test
	public void isBeforeChanceMoveTestWithCards() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));

		assertEquals(false, board.isBeforeChanceMove(new Move("Q")));
		assertEquals(false, board.isBeforeChanceMove(new Move("J")));
		
	}
	
	@Test
	public void isTerminalForMoveTestWithFalseExpected() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));

		assertEquals(false, board.isTerminalForMove(new Move("Q")));
		
	}
	
	@Test
	public void isTerminalForMoveTestWithTrueExpected() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		board.makeMoveForCard(new Move("ch"), new Move("Q"));

		assertEquals(true, board.isTerminalForMove(new Move("ch")));
		
	}
	
	@Test
	public void isTerminalForMoveTestWithTrueExpectedOne() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("Q"));
		board.makeMoveForCard(new Move("c"), new Move("Q"));
		board.makeMoveForCard(new Move("J"), new Move("Q"));
		board.makeMoveForCard(new Move("b"), new Move("Q"));

		assertEquals(true, board.isTerminalForMove(new Move("c")));
		
	}
	
	@Test
	public void isTerminalForMoveTestWithTrueExpectedTwo() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("c"), new Move("J"));
		board.makeMoveForCard(new Move("K"), new Move("J"));
		board.makeMoveForCard(new Move("ch"), new Move("J"));
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("r"), new Move("Q"));

		assertEquals(true, board.isTerminalForMove(new Move("c")));
		
	}
	
	@Test
	public void isAfterChanceWithTrueExpected() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("c"), new Move("J"));
		board.makeMoveForCard(new Move("K"), new Move("J"));

		assertEquals(true, board.isAfterChance());
		
	}
	
	@Test
	public void isAfterChanceWithFalseExpected() {
		
		SimulationBoard board = new SimulationBoard(new Board(new Move("J"), new Move("J")), new Move("K"));
		
		board.makeMoveForCard(new Move("b"), new Move("J"));
		board.makeMoveForCard(new Move("c"), new Move("J"));
		board.makeMoveForCard(new Move("K"), new Move("J"));
		board.makeMoveForCard(new Move("b"), new Move("J"));

		assertEquals(false, board.isAfterChance());
		
	}
	

}
